/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "wifi_device_util.h"

#include <stdio.h>

#include "cmsis_os.h"
#include "samgr/common.h"
#include "ohos_init.h"

#include "wifi_hotspot_config.h"

#define WIFI_WAIT_FOREVER 0xFFFFFFFF
#define CHANNEL_80211B_ONLY 14
#define FREQ_OF_CHANNEL_1 2412
#define FREQ_OF_CHANNEL_80211B_ONLY 2484
#define WIFI_MIN_CHANNEL 1
#define WIFI_FREQ_INTERVAL 5

static MutexId g_wifiGlobalLock = NULL;
static MutexId g_wifiEventLock = NULL;

WifiSecurityType HiSecToHoSec(xr_wifi_auth_mode mode)
{
    switch (mode) {
    case XR_WIFI_SECURITY_OPEN:
        return WIFI_SEC_TYPE_OPEN;
    case XR_WIFI_SECURITY_WEP:
        return WIFI_SEC_TYPE_WEP;
    case XR_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX:
    case XR_WIFI_SECURITY_WPAPSK:
    case XR_WIFI_SECURITY_WPA2PSK:
        return WIFI_SEC_TYPE_PSK;
    case XR_WIFI_SECURITY_SAE:
        return WIFI_SEC_TYPE_SAE;
    default:
        return WIFI_SEC_TYPE_INVALID;
    }
}

xr_wifi_auth_mode HoSecToHiSec(WifiSecurityType type)
{
    switch (type) {
    case WIFI_SEC_TYPE_OPEN:
        return XR_WIFI_SECURITY_OPEN;
    case WIFI_SEC_TYPE_WEP:
        return XR_WIFI_SECURITY_WEP;
    case WIFI_SEC_TYPE_PSK:
        return XR_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX;
    case WIFI_SEC_TYPE_SAE:
        return XR_WIFI_SECURITY_SAE;
    default:
        return XR_WIFI_SECURITY_UNKNOWN;
    }
}

void InitWifiGlobalLock(void)
{
    if (g_wifiGlobalLock == NULL) {
        osMutexAttr_t globalMutexAttr = { "WifiGloablLock",
                          osMutexRecursive |
                              osMutexPrioInherit,
                          NULL, 0U };
        g_wifiGlobalLock = osMutexNew(&globalMutexAttr);
    }

    if (g_wifiEventLock == NULL) {
        osMutexAttr_t eventMutexAttr = { "WifiEventLock",
                         osMutexRecursive |
                             osMutexPrioInherit,
                         NULL, 0U };
        g_wifiEventLock = osMutexNew(&eventMutexAttr);
    }
}

WifiErrorCode LockWifiGlobalLock(void)
{
    if (g_wifiGlobalLock == NULL) {
        return ERROR_WIFI_UNKNOWN;
    }

    osStatus_t ret = osMutexAcquire(g_wifiGlobalLock, WIFI_WAIT_FOREVER);
    if (ret != osOK) {
        printf("[wifi_service] osMutexAcquire failed \n");
        return ERROR_WIFI_UNKNOWN;
    }

    return WIFI_SUCCESS;
}

WifiErrorCode UnlockWifiGlobalLock(void)
{
    if (g_wifiGlobalLock == NULL) {
        return ERROR_WIFI_UNKNOWN;
    }

    osStatus_t ret = osMutexRelease(g_wifiGlobalLock);
    if (ret != osOK) {
        printf("[wifi_service] osMutexUnlock failed \n");
        return ERROR_WIFI_UNKNOWN;
    }

    return WIFI_SUCCESS;
}

WifiErrorCode LockWifiEventLock(void)
{
    if (g_wifiEventLock == NULL) {
        return ERROR_WIFI_UNKNOWN;
    }

    osStatus_t ret = osMutexAcquire(g_wifiEventLock, WIFI_WAIT_FOREVER);
    if (ret != osOK) {
        printf("[wifi_service] osMutexAcquire event failed \n");
        return ERROR_WIFI_UNKNOWN;
    }

    return WIFI_SUCCESS;
}

WifiErrorCode UnlockWifiEventLock(void)
{
    if (g_wifiEventLock == NULL) {
        return ERROR_WIFI_UNKNOWN;
    }

    osStatus_t ret = osMutexRelease(g_wifiEventLock);
    if (ret != osOK) {
        printf("[wifi_service] osMutexUnlock event failed \n");
        return ERROR_WIFI_UNKNOWN;
    }

    return WIFI_SUCCESS;
}

unsigned int ChannelToFrequency(unsigned int channel)
{
    if (channel == CHANNEL_80211B_ONLY) {
        return FREQ_OF_CHANNEL_80211B_ONLY;
    }
    return (((channel - WIFI_MIN_CHANNEL) * WIFI_FREQ_INTERVAL) +
        FREQ_OF_CHANNEL_1);
}

unsigned int FrequencyToChannel(unsigned int frequency)
{
    if (frequency == FREQ_OF_CHANNEL_80211B_ONLY) {
        return CHANNEL_80211B_ONLY;
    }

    if (frequency < FREQ_OF_CHANNEL_1) {
        return 0;
    }

    return (frequency - FREQ_OF_CHANNEL_1) / WIFI_FREQ_INTERVAL +
           WIFI_MIN_CHANNEL;
}

CORE_INIT(InitWifiGlobalLock);
